package com.jfee.dds.datasource;

import org.apache.tomcat.jdbc.pool.DataSource;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 动态数据源管理器。
 *
 * @author sf.xiong
 * @version 2019-05-31
 */
public class DDSHolder {

    /**
     * 管理动态数据源列表。<工程编码，数据源>
     */
    private ThreadLocal<Map<String, DDSTimer>> currDdsMap = new ThreadLocal<>();

    /**
     * 通过定时任务周期性清除不使用的数据源
     */
    private static Timer clearIdleTask = new Timer();

    static {
        clearIdleTask.schedule(new ClearIdleTimerTask(), 5000, 60 * 1000);
    }

    private DDSHolder() {

    }

    /*
     * 获取单例对象
     */
    public static DDSHolder instance() {
        return DDSHolderBuilder.instance;
    }

    /**
     * 添加动态数据源。
     *
     * @param tenantId 项目编码
     * @param dds      dds
     */
    public synchronized void addDDS(String tenantId, DataSource dds) {
        DDSTimer ddst = new DDSTimer(dds);
        Map<String, DDSTimer> ddsMap = currDdsMap.get();
        if (ddsMap == null) {
            ddsMap = new ConcurrentHashMap<>();
            ddsMap.put(tenantId, ddst);
            currDdsMap.set(ddsMap);
        }
    }

    /**
     * 查询动态数据源
     *
     * @param tenantId 项目编码
     * @return dds
     */
    public synchronized DataSource getDDS(String tenantId) {
        Map<String, DDSTimer> ddsMap = currDdsMap.get();
        if (ddsMap != null && ddsMap.containsKey(tenantId)) {
            DDSTimer ddsTimer = ddsMap.get(tenantId);
            ddsTimer.refreshTime();
            return ddsTimer.getDds();
        }

        return null;
    }

    /**
     * 清除超时无人使用的数据源。
     */
    public synchronized void clearIdleDDS() {
        if (currDdsMap.get() != null) {
            Iterator<Entry<String, DDSTimer>> iter = currDdsMap.get().entrySet().iterator();
            for (; iter.hasNext(); ) {

                Entry<String, DDSTimer> entry = iter.next();
                if (entry.getValue().checkAndClose()) {
                    iter.remove();
                }
            }
        }
    }

    /**
     * 单例构件类
     *
     * @author sf.xiong
     * @version 2019-05-31
     */
    private static class DDSHolderBuilder {
        private static DDSHolder instance = new DDSHolder();
    }
}
